package de.tu_darmstadt.gdi1.xcom.tests.testcases.tutors;

import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;

import org.junit.Before;
import org.junit.Test;

import de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel4;

/**
 * 
 * Tests for actions performed by humans automatically after KI-actions
 * 
 * @author Lukas Schwoebel
 *
 */
public class AutoActionTest {
	
	private XcomTestAdapterLevel4 testAdapter;
	
	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		testAdapter = new XcomTestAdapterLevel4();
	}

	/**
	 * Test method for {@link de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel4#performActionForPlayer()}.
	 */
	@Test
	public final void testAutoActions() {

		testAdapter.loadLevelFromString(TestLevel.testLevel);
		
		// move with human 1:4 to 2:4
		testAdapter.changeActivePlayer(1, 4);
		testAdapter.rotateActivePlayer(true);
		testAdapter.performActionForActivePlayer();
		
		// now turn of zombies
		// turn zombie to begin zombie-turn
		testAdapter.performKIAction("2;2;l");	
		
		// save gamestate
		String gameState = testAdapter.returnGamestateAsSavegame();
		
		// test for all players if they perform any auto-action
		testAdapter.performActionForPlayer(2, 4);
		// no action, player is not looking north to a zombie
		assertEquals("No zombie in line of sight of any player, so the gamestate should not have changed!", gameState, testAdapter.returnGamestateAsSavegame());
		
		// begin turn of humans again and turn human on 2:4
		testAdapter.endTurn();
		testAdapter.changeActivePlayer(2, 4);
		testAdapter.rotateActivePlayer(false);
		// start zombie-turn again
		testAdapter.performKIAction("2;2;r");
				
		// perform auto-action, should kill the zombie
		testAdapter.performActionForPlayer(2, 4);
		
		// re-save gamestate
		gameState = testAdapter.returnGamestateAsSavegame();
		
		// test if zombie was killed
		assertTrue("Zombie should have been killed, munition and actionpoints of player at 2:4 should have decreased." + gameState, gameState.contains("@;2;4;n;50;64;50;50;9"));
		assertEquals("Zombie should have been killed at 2:2, a floor element should remain", '.', testAdapter.elementOnPosition(2, 2));
	}

	/**
	 * Test method for {@link de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel4#performActionForPlayer()}.
	 */
	@Test
	public final void testAutoActionsHealthPoints() {

		// give to-be-killed-zombie different amount of healthpoints
		testAdapter.loadLevelFromString(TestLevel.testLevel.replaceAll("Z;2;2;n;50;75;50;0;0", "Z;2;2;n;90;75;50;0;0"));
		
		// move with human 1:4 to 2:4 and turn north
		testAdapter.changeActivePlayer(1, 4);
		testAdapter.rotateActivePlayer(true);
		testAdapter.performActionForActivePlayer();
		testAdapter.rotateActivePlayer(false);
		
		// start zombie-turn
		testAdapter.performKIAction("2;2;r");
				
		// perform auto-action, should kill the zombie
		testAdapter.performActionForPlayer(2, 4);
		
		// re-save gamestate
		String gameState = testAdapter.returnGamestateAsSavegame();
		
		// test if zombie was killed
		assertTrue("Munition and actionpoints of player at 2:4 should have decreased." + gameState, gameState.contains("@;2;4;n;50;60;50;50;9"));
		assertEquals("Zombie should still be alive at 2:2", 'Z', testAdapter.elementOnPosition(2, 2));
		assertTrue("Zombie should still be alive at 2:2 have 40 healthpoints" + gameState, gameState.contains("Z;2;2;e;40;74;50;0;0"));
		
		// now shoot again
		testAdapter.performActionForPlayer(2, 4);
		// re-save gamestate
		gameState = testAdapter.returnGamestateAsSavegame();
		assertTrue("Zombie should have been killed, munition and actionpoints of player at 2:4 should have decreased." + gameState, gameState.contains("@;2;4;n;50;50;50;50;8"));
		assertEquals("Zombie should have been killed at 2:2, a floor element should remain", '.', testAdapter.elementOnPosition(2, 2));
		
		// shoot again
		testAdapter.performActionForPlayer(2, 4);
		assertEquals("The gamestate should not have changed as there was nothing to shoot at", gameState, testAdapter.returnGamestateAsSavegame());
	}

	/**
	 * Test method for {@link de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel4#performActionForPlayer()}.
	 */
	@Test
	public final void testAutoActionsWithWall() {

		String testLevel = "" +
				"########\n" +
				"#......#\n" +
				"#..##..#\n" +
				"#......#\n" +
				"########\n" +
				"//{mobs}\n" +
				"//@;3;3;n;50;75;50;50;10\n" +
				"//Z;3;1;n;50;75;50;0;0";
		
		// give to-be-killed-zombie different amount of healthpoints
		testAdapter.loadLevelFromString(testLevel);
				
		// start zombie-turn
		testAdapter.performKIAction("3;1;r");				
		// perform auto-action, should kill the zombie
		testAdapter.performActionForPlayer(2, 4);
		
		// re-save gamestate
		String gameState = testAdapter.returnGamestateAsSavegame();
		
		// test if zombie was killed
		assertTrue("There is a wall between zombie and human, can't perform auto-shoot" + gameState, gameState.contains("@;3;3;n;50;75;50;50;10"));
		assertEquals("Zombie should still be alive at 3:1", 'Z', testAdapter.elementOnPosition(3, 1));
		assertTrue("Zombie should still be alive at 2:2 have 50 healthpoints" + gameState, gameState.contains("Z;3;1;e;50;74;50;0;0"));
	}

	/**
	 * Test method for {@link de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel4#performActionForPlayer()}.
	 */
	@Test
	public final void testAutoActionsWithDoor() {

		String testLevel = "" +
				"########\n" +
				"#......#\n" +
				"#...#..#\n" +
				"#......#\n" +
				"########\n" +
				"//{mobs}\n" +
				"//@;3;3;n;50;75;50;50;10\n" +
				"//Z;3;1;n;50;75;50;0;0\n" +
				"//{doors}\n" +
				"//3;4;3;2;c";		
		
		// now test with door in both states
		testAdapter.loadLevelFromString(testLevel);
				
		// start zombie-turn
		testAdapter.performKIAction("3;1;r");				
		// perform auto-action, should kill the zombie
		testAdapter.performActionForPlayer(2, 4);
		
		// re-save gamestate
		String gameState = testAdapter.returnGamestateAsSavegame();
		
		// test if zombie was killed
		assertTrue("There is a closed door between zombie and human, can't perform auto-shoot" + gameState, gameState.contains("@;3;3;n;50;75;50;50;10"));
		assertEquals("Zombie should still be alive at 3:1", 'Z', testAdapter.elementOnPosition(3, 1));
		assertTrue("Zombie should still be alive at 3:1 have 50 healthpoints" + gameState, gameState.contains("Z;3;1;e;50;74;50;0;0"));
		
		// now open door south of player and turn north again
		testAdapter.endTurn();
		testAdapter.rotateActivePlayer(true);
		testAdapter.rotateActivePlayer(true);
		testAdapter.performActionForActivePlayer();
		testAdapter.rotateActivePlayer(true);
		testAdapter.rotateActivePlayer(true);
		
		// start zombie-turn
		testAdapter.performKIAction("3;1;l");
		testAdapter.performActionForPlayer(3, 3);
		
		// re-save gamestate
		gameState = testAdapter.returnGamestateAsSavegame();
		
		// test if zombie was killed
		assertTrue("There is an open door between zombie and human, should be able to shoot" + gameState, gameState.contains("@;3;3;n;50;61;50;50;9"));
		assertEquals("Zombie should be dead at 3:1", '.', testAdapter.elementOnPosition(3, 1));
	}
}
